﻿using System;
using System.Collections.Generic;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Utilities;

namespace GDExtensions
{
    /// <summary>
    /// Extension methods for the <see cref="T:Microsoft.SharePoint.SPSite"/> class.
    /// </summary>
    /// <remarks></remarks>
    public static class SPSiteExtensions
    {
        #region Public Methods
        /// <summary>
        /// Method to add the <paramref name="groupName"/> to the <paramref name="site"/>'s root web.
        /// </summary>
        /// <param name="site">The <see cref="T:Microsoft.SharePoint.SPSite"/> site.</param>
        /// <param name="groupName">The name of the <see cref="T:Microsoft.SharePoint.SPGroup"/> group.</param>
        /// <param name="roleType">The <see cref="T:Microsoft.SharePoint.SPRoleType"/> role for the <paramref name="group"/>.</param>
        /// <returns><c>true</c> if <paramref name="groupName"/> is added successfully; otherwise, <c>false</c>.</returns>
        /// <remarks></remarks>
        public static bool AddSecurityGroup(this SPSite site, string groupName, SPRoleType roleType)
        {
            // Add the security group to the root web
            return site.RootWeb.AddSecurityGroup(groupName, roleType);
        }

        /// <summary>
        /// Method to add the <paramref name="group"/> to the <paramref name="site"/>'s root web.
        /// </summary>
        /// <param name="site">The <see cref="T:Microsoft.SharePoint.SPSite"/> site.</param>
        /// <param name="group">The <see cref="T:Microsoft.SharePoint.SPGroup"/> group to add.</param>
        /// <param name="roleType">The <see cref="T:Microsoft.SharePoint.SPRoleType"/> role for the <paramref name="group"/>.</param>
        /// <returns><c>true</c> if <paramref name="group"/> is added successfully; otherwise, <c>false</c>.</returns>
        /// <remarks></remarks>
        public static bool AddSecurityGroup(this SPSite site, SPGroup group, SPRoleType roleType)
        {
            // Add the security group to the root web
            return site.RootWeb.AddSecurityGroup(group, roleType);
        }

        /// <summary>
        /// Method to add the <paramref name="groupName"/> to the <paramref name="site"/>'s root web.
        /// </summary>
        /// <param name="site">The <see cref="T:Microsoft.SharePoint.SPSite"/> site.</param>
        /// <param name="groupName">The name of the <see cref="T:Microsoft.SharePoint.SPGroup"/> group.</param>
        /// <param name="roleDefinition">The <see cref="T:Microsoft.SharePoint.SPRoleDefinition"/> role definition for the <paramref name="group"/>.</param>
        /// <returns><c>true</c> if <paramref name="groupName"/> is added successfully; otherwise, <c>false</c>.</returns>
        /// <remarks></remarks>
        public static bool AddSecurityGroup(this SPSite site, string groupName, SPRoleDefinition roleDefinition)
        {
            // Add the security group to the root web
            return site.RootWeb.AddSecurityGroup(groupName, roleDefinition);
        }

        /// <summary>
        /// Method to add the <paramref name="group"/> to the <paramref name="site"/>'s root web.
        /// </summary>
        /// <param name="site">The <see cref="T:Microsoft.SharePoint.SPSite"/> site.</param>
        /// <param name="group">The <see cref="T:Microsoft.SharePoint.SPGroup"/> group to add.</param>
        /// <param name="roleDefinition">The <see cref="T:Microsoft.SharePoint.SPRoleDefinition"/> role definition for the <paramref name="group"/>.</param>
        /// <returns><c>true</c> if <paramref name="group"/> is added successfully; otherwise, <c>false</c>.</returns>
        /// <remarks></remarks>
        public static bool AddSecurityGroup(this SPSite site, SPGroup group, SPRoleDefinition roleDefinition)
        {
            // Call the private method
            return _AddSecurityGroup(site, group, roleDefinition);
        }

        /// <summary>
        /// Method to create the <paramref name="groupName"/> to the <paramref name="site"/>'s root web.
        /// </summary>
        /// <param name="site">The <see cref="T:Microsoft.SharePoint.SPSite"/> site.</param>
        /// <param name="groupName">The name of the <see cref="T:Microsoft.SharePoint.SPGroup"/> group.</param>
        /// <param name="description">The <see cref="T:Microsoft.SharePoint.SPGroup"/> description.</param>
        /// <param name="roleType">The <see cref="T:Microsoft.SharePoint.SPGroup"/> <see cref="T:Microsoft.SharePoint.SPRoleType"/>.</param>
        /// <returns>The <paramref name="groupName"/> as a <see cref="T:Microsoft.SharePoint.SPGroup"/>.</returns>
        /// <remarks></remarks>
        public static SPGroup CreateSecurityGroup(this SPSite site, string groupName, string description, SPRoleType roleType)
        {
            // Create the security group
            return site.CreateSecurityGroup(groupName, description, roleType, false);
        }

        /// <summary>
        /// Method to create the <paramref name="groupName"/> to the <paramref name="site"/>'s root web.
        /// </summary>
        /// <param name="site">The <see cref="T:Microsoft.SharePoint.SPSite"/> site.</param>
        /// <param name="groupName">The name of the <see cref="T:Microsoft.SharePoint.SPGroup"/> group.</param>
        /// <param name="description">The <see cref="T:Microsoft.SharePoint.SPGroup"/> description.</param>
        /// <param name="roleType">The <see cref="T:Microsoft.SharePoint.SPGroup"/> <see cref="T:Microsoft.SharePoint.SPRoleType"/>.</param>
        /// <param name="ownersGroup">The owner of the <paramref name="groupName"/>.</param>
        /// <returns>The <paramref name="groupName"/> as a <see cref="T:Microsoft.SharePoint.SPGroup"/>.</returns>
        /// <remarks></remarks>
        public static SPGroup CreateSecurityGroup(this SPSite site, string groupName, string description, SPRoleType roleType,
            SPGroup ownersGroup)
        {
            // Create the security group
            return site.CreateSecurityGroup(groupName, description, roleType, ownersGroup, false);
        }

        /// <summary>
        /// Method to create the <paramref name="groupName"/> to the <paramref name="site"/>'s root web.
        /// </summary>
        /// <param name="site">The <see cref="T:Microsoft.SharePoint.SPSite"/> site.</param>
        /// <param name="groupName">The name of the <see cref="T:Microsoft.SharePoint.SPGroup"/> group.</param>
        /// <param name="description">The <see cref="T:Microsoft.SharePoint.SPGroup"/> description.</param>
        /// <param name="roleType">The <see cref="T:Microsoft.SharePoint.SPGroup"/> <see cref="T:Microsoft.SharePoint.SPRoleType"/>.</param>
        /// <param name="owner">The owner of the <paramref name="groupName"/>.</param>
        /// <returns>The <paramref name="groupName"/> as a <see cref="T:Microsoft.SharePoint.SPGroup"/>.</returns>
        /// <remarks></remarks>
        public static SPGroup CreateSecurityGroup(this SPSite site, string groupName, string description, SPRoleType roleType,
            SPUser owner)
        {
            // Create the security group
            return site.CreateSecurityGroup(groupName, description, roleType, owner, false);
        }

        /// <summary>
        /// Method to create the <paramref name="groupName"/> to the <paramref name="site"/>'s root web.
        /// </summary>
        /// <param name="site">The <see cref="T:Microsoft.SharePoint.SPSite"/> site.</param>
        /// <param name="groupName">The name of the <see cref="T:Microsoft.SharePoint.SPGroup"/> group.</param>
        /// <param name="description">The <see cref="T:Microsoft.SharePoint.SPGroup"/> description.</param>
        /// <param name="roleType">The <see cref="T:Microsoft.SharePoint.SPGroup"/> <see cref="T:Microsoft.SharePoint.SPRoleType"/>.</param>
        /// <param name="deleteExisting">if set to <c>true</c> deletes the existing <see cref="T:Microsoft.SharePoint.SPGroup"/>.</param>
        /// <returns>The <paramref name="groupName"/> as a <see cref="T:Microsoft.SharePoint.SPGroup"/>.</returns>
        /// <remarks></remarks>
        public static SPGroup CreateSecurityGroup(this SPSite site, string groupName, string description, SPRoleType roleType,
            bool deleteExisting)
        {
            // Ensure the web exists
            if (site == null) { return default(SPGroup); }

            // Create the security group
            return site.RootWeb.CreateSecurityGroup(groupName, description, roleType, deleteExisting);
        }

        /// <summary>
        /// Method to create the <paramref name="groupName"/> to the <paramref name="site"/>'s root web.
        /// </summary>
        /// <param name="site">The <see cref="T:Microsoft.SharePoint.SPSite"/> site.</param>
        /// <param name="groupName">The name of the <see cref="T:Microsoft.SharePoint.SPGroup"/> group.</param>
        /// <param name="description">The <see cref="T:Microsoft.SharePoint.SPGroup"/> description.</param>
        /// <param name="roleType">The <see cref="T:Microsoft.SharePoint.SPGroup"/> <see cref="T:Microsoft.SharePoint.SPRoleType"/>.</param>
        /// <param name="ownersGroup">The owner of the <see cref="T:Microsoft.SharePoint.SPGroup"/> group.</param>
        /// <param name="deleteExisting">if set to <c>true</c> deletes the existing <see cref="T:Microsoft.SharePoint.SPGroup"/>.</param>
        /// <returns>The <paramref name="groupName"/> as a <see cref="T:Microsoft.SharePoint.SPGroup"/>.</returns>
        /// <remarks></remarks>
        public static SPGroup CreateSecurityGroup(this SPSite site, string groupName, string description, SPRoleType roleType,
            SPGroup ownersGroup, bool deleteExisting)
        {
            // Ensure the web exists
            if (site == null) { return default(SPGroup); }

            // Create the security group
            return site.RootWeb.CreateSecurityGroup(groupName, description, roleType, ownersGroup, deleteExisting);
        }

        /// <summary>
        /// Method to create the <paramref name="groupName"/> to the <paramref name="site"/>'s root web.
        /// </summary>
        /// <param name="site">The <see cref="T:Microsoft.SharePoint.SPSite"/> site.</param>
        /// <param name="groupName">The name of the <see cref="T:Microsoft.SharePoint.SPGroup"/> group.</param>
        /// <param name="description">The <see cref="T:Microsoft.SharePoint.SPGroup"/> description.</param>
        /// <param name="roleType">The <see cref="T:Microsoft.SharePoint.SPGroup"/> <see cref="T:Microsoft.SharePoint.SPRoleType"/>.</param>
        /// <param name="owner">The owner of the <paramref name="groupName"/>.</param>
        /// <param name="deleteExisting">if set to <c>true</c> deletes the existing <see cref="T:Microsoft.SharePoint.SPGroup"/>.</param>
        /// <returns>The <paramref name="groupName"/> as a <see cref="T:Microsoft.SharePoint.SPGroup"/>.</returns>
        /// <remarks></remarks>
        public static SPGroup CreateSecurityGroup(this SPSite site, string groupName, string description, SPRoleType roleType,
            SPUser owner, bool deleteExisting)
        {
            // Call the private method
            return _CreateSecurityGroup(site, groupName, description, roleType, owner, deleteExisting);
        }

        /// <summary>
        /// Method to create the <paramref name="name"/> custom permission level for the <paramref name="site"/>.
        /// </summary>
        /// <param name="site">The <see cref="T:Microsoft.SharePoint.SPSite"/> site.</param>
        /// <param name="permissionLevelName">The name of the <see cref="T:Microsoft.SharePoint.SPRoleDefinition"/>.</param>
        /// <param name="description">The description of the <see cref="T:Microsoft.SharePoint.SPRoleDefinition"/>.</param>
        /// <param name="permissions">The <see cref="T:Microsoft.SharePoint.SPBasePermissions"/> of the <see cref="T:Microsoft.SharePoint.SPRoleDefinition"/>.</param>
        /// <remarks></remarks>
        public static void CreatePermissionLevel(this SPSite site, string permissionLevelName, string description, SPBasePermissions permissions)
        {
            // Call the private method
            _CreatePermissionLevel(site, permissionLevelName, description, permissions);
        }

        /// <summary>
        /// Method to delete the <paramref name="groupName"/> from the <paramref name="site"/>'s root web.
        /// </summary>
        /// <param name="site">The <see cref="T:Microsoft.SharePoint.SPSite"/> site.</param>
        /// <returns>The <see cref="T:Microsoft.SharePoint.SPGroup"/>.</returns>
        /// <remarks></remarks>
        public static void DeleteSecurityGroup(this SPSite site, string groupName)
        {
            // Ensure the site exists
            if (site == null) { return; }

            // Delete the security group
            site.RootWeb.DeleteSecurityGroup(groupName);
        }

        /// <summary>
        /// Method to delete the <paramref name="groupName"/> from the <paramref name="site"/>'s root web.
        /// </summary>
        /// <param name="site">The <see cref="T:Microsoft.SharePoint.SPSite"/> site.</param>
        /// <param name="group">The <see cref="T:Microsoft.SharePoint.SPGroup"/> group to delete.</param>
        /// <returns>The <see cref="T:Microsoft.SharePoint.SPGroup"/>.</returns>
        /// <remarks></remarks>
        public static void DeleteSecurityGroup(this SPSite site, SPGroup group)
        {
            // Ensure the site exists
            if (site == null) { return; }

            // Delete the security group
            site.RootWeb.DeleteSecurityGroup(group);
        }

        /// <summary>
        /// Method to determine if a file exists.
        /// </summary>
        /// <param name="site">The <see cref="T:Microsoft.SharePoint.SPSite"/> site.</param>
        /// <param name="url">The url of the file.</param>
        /// <returns>True/False if the file exists.</returns>
        public static SPFile FileExists(this SPSite site, string url)
        {
            // Call the private method
            return _FileExists(site, url);
        }

        /// <summary>
        /// Method to remove the master page.
        /// </summary>
        /// <param name="site">The <see cref="T:Microsoft.SharePoint.SPSite"/> site.</param>
        /// <param name="masterPage">The name of the master page.</param>
        public static void RemoveMasterPage(this SPSite site, string masterPage)
        {
            // Call the private method
            _RemoveMasterPage(site, masterPage);
        }

        /// <summary>
        /// Method to remove the <paramref name="groupName"/> from the <paramref name="site"/>'s root web.
        /// </summary>
        /// <param name="site">The <see cref="T:Microsoft.SharePoint.SPSite"/> site.</param>
        /// <param name="groupName">The name of the <see cref="T:Microsoft.SharePoint.SPGroup"/> group to remove.</param>
        /// <remarks></remarks>
        public static void RemoveSecurityGroup(this SPSite site, string groupName)
        {
            // Ensure the site exists
            if (site == null) { return; }

            // Remove the group
            site.RootWeb.RemoveSecurityGroup(groupName);
        }

        /// <summary>
        /// Method to remove the <paramref name="groupName"/> from the <paramref name="site"/>'s root web.
        /// </summary>
        /// <param name="site">The <see cref="T:Microsoft.SharePoint.SPSite"/> site.</param>
        /// <param name="group">The <see cref="T:Microsoft.SharePoint.SPGroup"/> group to add.</param>
        /// <remarks></remarks>
        public static void RemoveSecurityGroup(this SPSite site, SPGroup group)
        {
            // Ensure the site exists
            if (site == null) { return; }

            // Remove the group
            site.RootWeb.RemoveSecurityGroup(group.Name);
        }

        /// <summary>
        /// Method to remove the <paramref name="webPartNames"/> from the "Web Part Gallery" list.
        /// </summary>
        /// <param name="site">The <see cref="T:Microsoft.SharePoint.SPSite"/> site.</param>
        /// <param name="webPartNames">The list of web part names.</param>
        /// <remarks></remarks>
        public static void RemoveWebParts(this SPSite site, List<string> webPartNames)
        {
            // Call the private method
            _RemoveWebParts(site, webPartNames);
        }

        /// <summary>
        /// Method to elevate and run the <paramref name="methodToElevate"/> as an administrator, against the <paramref name="site"/>'s root web.
        /// </summary>
        /// <param name="site">The <see cref="T:Microsoft.SharePoint.SPSite"/> site.</param>
        /// <param name="methodToElevate">The method to elevate.</param>
        /// <remarks></remarks>
        public static void RunAsAdmin(this SPSite site, Action<SPSite> methodToElevate)
        {
            // Call the private method
            _RunAsAdmin(site, methodToElevate);
        }

        /// <summary>
        /// Method to elevate and run the <paramref name="methodToElevate"/> as an administrator, against the <paramref name="site"/>'s root web.
        /// </summary>
        /// <param name="site">The <see cref="T:Microsoft.SharePoint.SPSite"/> site.</param>
        /// <param name="methodToElevate">The method to elevate.</param>
        /// <param name="inputArgs">The <see cref="InputParameters"/> for <paramref name="methodToElevate"/>.</param>
        /// <returns>Return object from the <paramref name="methodToElevate"/>.</returns>
        /// <remarks></remarks>
        public static object RunAsAdmin(this SPSite site, Func<InputParameters, object> methodToElevate, params object[] inputArgs)
        {
            // Call the private method
            return _RunAsAdmin(site, methodToElevate, inputArgs);
        }

        /// <summary>
        /// Method to update the master page.
        /// </summary>
        /// <param name="site">The <see cref="T:Microsoft.SharePoint.SPSite"/> site.</param>
        /// <param name="masterPageUrl">The master page url.</param>
        /// <param name="siteLogoDescription">The site logo description.</param>
        /// <param name="siteLogoUrl">The site logo url.</param>
        /// <param name="uiVersionNumber">The UI Version number.</param>
        /// <param name="updateSubWebsFl">The flag to update all sub-webs.</param>
        public static void UpdateMasterPage(this SPSite site, string masterPageUrl,
            string siteLogoDescription, string siteLogoUrl, int uiVersionNumber, bool updateSubWebsFl)
        {
            // Update the master page
            site.UpdateMasterPage(masterPageUrl, masterPageUrl, siteLogoDescription, siteLogoUrl, uiVersionNumber, updateSubWebsFl);
        }

        /// <summary>
        /// Method to update the master page.
        /// </summary>
        /// <param name="site">The <see cref="T:Microsoft.SharePoint.SPSite"/> site.</param>
        /// <param name="customMasterUrl">The custom master page url.</param>
        /// <param name="masterPageUrl">The master page url.</param>
        /// <param name="siteLogoDescription">The site logo description.</param>
        /// <param name="siteLogoUrl">The site logo url.</param>
        /// <param name="uiVersionNumber">The UI Version number.</param>
        /// <param name="updateSubWebsFl">The flag to update all sub-webs.</param>
        public static void UpdateMasterPage(this SPSite site, string customMasterUrl, string masterPageUrl,
            string siteLogoDescription, string siteLogoUrl, int uiVersionNumber, bool updateSubWebsFl)
        {
            // Call the private method
            _UpdateMasterPage(site, customMasterUrl, masterPageUrl, siteLogoDescription, siteLogoUrl, uiVersionNumber, updateSubWebsFl);
        }
        #endregion

        #region Private Methods
        /// <summary>
        /// Method to add the <paramref name="group"/> to the <paramref name="site"/>'s root web.
        /// </summary>
        /// <param name="site">The <see cref="T:Microsoft.SharePoint.SPSite"/> site.</param>
        /// <param name="group">The <see cref="T:Microsoft.SharePoint.SPGroup"/> group to add.</param>
        /// <param name="roleDefinition">The <see cref="T:Microsoft.SharePoint.SPRoleDefinition"/> role definition for the <paramref name="group"/>.</param>
        /// <returns><c>true</c> if <paramref name="group"/> is added successfully; otherwise, <c>false</c>.</returns>
        /// <remarks></remarks>
        private static bool _AddSecurityGroup(SPSite site, SPGroup group, SPRoleDefinition roleDefinition)
        {
            // Add the security group to the root web
            return site.RootWeb.AddSecurityGroup(group, roleDefinition);
        }

        /// <summary>
        /// Method to create the <paramref name="groupName"/> to the <paramref name="site"/>'s root web.
        /// </summary>
        /// <param name="site">The <see cref="T:Microsoft.SharePoint.SPSite"/> site.</param>
        /// <param name="groupName">The name of the <see cref="T:Microsoft.SharePoint.SPGroup"/> group.</param>
        /// <param name="description">The <see cref="T:Microsoft.SharePoint.SPGroup"/> description.</param>
        /// <param name="roleType">The <see cref="T:Microsoft.SharePoint.SPGroup"/> <see cref="T:Microsoft.SharePoint.SPRoleType"/>.</param>
        /// <param name="owner">The owner of the <paramref name="groupName"/>.</param>
        /// <param name="deleteExisting">if set to <c>true</c> deletes the existing <see cref="T:Microsoft.SharePoint.SPGroup"/>.</param>
        /// <returns>The <paramref name="groupName"/> as a <see cref="T:Microsoft.SharePoint.SPGroup"/>.</returns>
        /// <remarks></remarks>
        private static SPGroup _CreateSecurityGroup(SPSite site, string groupName, string description, SPRoleType roleType,
            SPUser owner, bool deleteExisting)
        {
            // Ensure the web exists
            if (site == null) { return default(SPGroup); }

            // Create the security group
            return site.RootWeb.CreateSecurityGroup(groupName, description, roleType, owner, deleteExisting);
        }

        /// <summary>
        /// Method to create the <paramref name="name"/> custom permission level for the <paramref name="site"/>.
        /// </summary>
        /// <param name="site">The <see cref="T:Microsoft.SharePoint.SPSite"/> site.</param>
        /// <param name="permissionLevelName">The name of the <see cref="T:Microsoft.SharePoint.SPRoleDefinition"/>.</param>
        /// <param name="description">The description of the <see cref="T:Microsoft.SharePoint.SPRoleDefinition"/>.</param>
        /// <param name="permissions">The <see cref="T:Microsoft.SharePoint.SPBasePermissions"/> of the <see cref="T:Microsoft.SharePoint.SPRoleDefinition"/>.</param>
        /// <remarks></remarks>
        private static void _CreatePermissionLevel(SPSite site, string permissionLevelName, string description, SPBasePermissions permissions)
        {
            // Parse the permission levels and ensure the CPO User permission is created
            foreach (SPRoleDefinition permissionLevel in site.RootWeb.RoleDefinitions)
            {
                if (permissionLevel.Name == permissionLevelName)
                {
                    // Permission level already exists
                    return;
                }
            }

            // Copy the reader role definition
            SPRoleDefinition roleDef = new SPRoleDefinition(site.RootWeb.RoleDefinitions.GetByType(SPRoleType.Reader));

            // Add the add & update permissions
            roleDef.BasePermissions |= permissions;
            roleDef.Description = description;
            roleDef.Name = permissionLevelName;

            // Save the new role assignment
            site.RootWeb.RoleDefinitions.Add(roleDef);
        }

        /// <summary>
        /// Method to determine if a file exists.
        /// </summary>
        /// <param name="site">The <see cref="T:Microsoft.SharePoint.SPSite"/> site.</param>
        /// <param name="url">The url of the file.</param>
        /// <returns>The file.</returns>
        private static SPFile _FileExists(SPSite site, string url)
        {
            // Return the existence of the file
            return site.RootWeb.FileExists(url);
        }

        /// <summary>
        /// Method to remove the master page.
        /// </summary>
        /// <param name="site">The <see cref="T:Microsoft.SharePoint.SPSite"/> site.</param>
        /// <param name="masterPage">The name of the master page.</param>
        private static void _RemoveMasterPage(SPSite site, string masterPage)
        {
            // Ensure the site exists
            if (site == null) { return; }

            // Get the master page
            SPFile file = site.RootWeb.GetFile(SPUrlUtility.CombineUrl(site.RootWeb.Url, "_catalogs/masterpage/" + masterPage));
            if (file != null && file.Exists)
            {
                // Set the default master page url
                string masterPageUrl = SPUrlUtility.CombineUrl(site.RootWeb.ServerRelativeUrl, "_catalogs/masterpage/v4.master");

                // Parse the webs
                for (int i = 0; i < site.AllWebs.Count; i++)
                {
                    SPWeb subWeb = site.AllWebs[i];

                    // Ensure this master page isn't active
                    if (subWeb.MasterUrl.EndsWith("/" + masterPage, StringComparison.CurrentCultureIgnoreCase))
                    {
                        // Set the default master page
                        subWeb.UpdateMasterPage(masterPageUrl, subWeb.SiteLogoDescription, subWeb.SiteLogoUrl, 4, false);
                    }

                    // Dispose of the sub web
                    subWeb.Dispose();
                }

                // Note - We need to refresh the web object associated with the file. If the associated web is
                //        still linked to the master page we are trying to remove, it will throw an error.
                // Open the site containing the file
                using (SPSite fileSite = new SPSite(site.Url))
                {
                    // Open the web containing the file
                    using (SPWeb fileWeb = fileSite.OpenWeb())
                    {
                        // Get the file
                        file = fileWeb.GetFile(file.Url);
                        if (file != null && file.Exists)
                        {
                            // Delete the master page
                            file.Delete();
                        }
                    }
                }
            }
        }

        /// <summary>
        /// Method to remove the <paramref name="webPartNames"/> from the "Web Part Gallery" list.
        /// </summary>
        /// <param name="site">The <see cref="T:Microsoft.SharePoint.SPSite"/> site.</param>
        /// <param name="webPartNames">The list of web part names.</param>
        /// <remarks></remarks>
        private static void _RemoveWebParts(SPSite site, List<string> webPartNames)
        {
            SPList webPartList = default(SPList);

            // Ensure the site exists
            if (site == null) { return; }

            // Ensure the web part names exist and contains values
            if (webPartNames == null || webPartNames.Count == 0)
            {
                return;
            }

            // Ensure each web part name is lower case
            for (int i = 0; i < webPartNames.Count; i++)
            {
                webPartNames[i] = webPartNames[i].ToLower();
            }

            // Get the web part gallery list
            webPartList = site.RootWeb.Lists.TryGetList("Web Part Gallery");
            if (webPartList != null && webPartList.ItemCount > 0)
            {
                // Parse the list items
                for (int i = webPartList.ItemCount - 1; i >= 0; i--)
                {
                    // See if we are removing this web part
                    if (webPartNames.Contains(webPartList.Items[i].Name.ToLower()))
                    {
                        // Remove the list item
                        webPartList.Items[i].Delete();
                    }
                }
            }
        }

        /// <summary>
        /// Method to elevate and run the <paramref name="methodToElevate"/> as an administrator, against the <paramref name="site"/>'s root web.
        /// </summary>
        /// <param name="site">The <see cref="T:Microsoft.SharePoint.SPSite"/> site.</param>
        /// <param name="methodToElevate">The method to elevate.</param>
        /// <remarks></remarks>
        private static void _RunAsAdmin(SPSite site, Action<SPSite> methodToElevate)
        {
            // Ensure the site exists
            if (site == null) { return; }

            // Run with elevated privileges
            SPSecurity.RunWithElevatedPrivileges(delegate()
            {
                // Create the elevated site object
                using (SPSite elevatedSite = new SPSite(site.ID))
                {
                    // Execute the method to elevate
                    methodToElevate(elevatedSite);
                }
            });
        }

        /// <summary>
        /// Method to elevate and run the <paramref name="methodToElevate"/> as an administrator, against the <paramref name="site"/>'s root web.
        /// </summary>
        /// <param name="site">The <see cref="T:Microsoft.SharePoint.SPSite"/> site.</param>
        /// <param name="methodToElevate">The method to elevate.</param>
        /// <param name="inputArgs">The <see cref="InputParameters"/> for <paramref name="methodToElevate"/>.</param>
        /// <returns>Return object from the <paramref name="methodToElevate"/>.</returns>
        /// <remarks></remarks>
        private static object _RunAsAdmin(SPSite site, Func<InputParameters, object> methodToElevate, params object[] inputArgs)
        {
            object returnVal = default(object);

            // Ensure the site exists
            if (site == null) { return returnVal; }

            // See if the current user is an admin
            if (site.RootWeb.CurrentUser.IsSiteAdmin)
            {
                // Execute the method to elevate
                returnVal = methodToElevate(new InputParameters(site, site.RootWeb, inputArgs));
            }
            // Else, run with elevated privilieges
            else
            {
                SPSecurity.RunWithElevatedPrivileges(delegate()
                {
                    // Create the elevated site object
                    using (SPSite elevatedSite = new SPSite(site.ID))
                    {
                        // Create the elevated web object
                        using (SPWeb elevatedWeb = elevatedSite.OpenWeb())
                        {
                            // Execute the method to elevate
                            returnVal = methodToElevate(new InputParameters(elevatedSite, elevatedWeb, inputArgs));
                        }
                    }
                });
            }

            return returnVal;
        }

        /// <summary>
        /// Method to update the master page.
        /// </summary>
        /// <param name="site">The <see cref="T:Microsoft.SharePoint.SPSite"/> site.</param>
        /// <param name="customMasterUrl">The custom master page url.</param>
        /// <param name="masterPageUrl">The master page url.</param>
        /// <param name="siteLogoDescription">The site logo description.</param>
        /// <param name="siteLogoUrl">The site logo url.</param>
        /// <param name="uiVersionNumber">The UI Version number.</param>
        /// <param name="updateSubWebsFl">The flag to update all sub-webs.</param>
        private static void _UpdateMasterPage(SPSite site, string customMasterUrl, string masterPageUrl,
            string siteLogoDescription, string siteLogoUrl, int uiVersionNumber, bool updateSubWebsFl)
        {
            // Update the master page on the root web.
            site.RootWeb.UpdateMasterPage(customMasterUrl, masterPageUrl, siteLogoDescription, siteLogoUrl, uiVersionNumber, updateSubWebsFl);
        }
        #endregion
    }
}
